/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.lundberg.podcasts;

import java.io.File;
import java.io.IOException;
import org.lundberg.podcasts.R;
import org.lundberg.podcasts.util.DownloadIconTask;
import org.lundberg.podcasts.util.PodcastDB;
import org.lundberg.podcasts.util.Util;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;


public class PlayerActivity extends Activity
{
	//private static final int DOWNLOAD_MENU_ITEM = Menu.FIRST;
	//private static final int CANCEL_DOWNLOAD_MENU_ITEM = Menu.FIRST+1;
	//private static final int REMOVE_DOWNLOAD_MENU_ITEM = Menu.FIRST+2;
	private int fwd_seek_amount = 0;
    private int rev_seek_amount = 0;
	private TextView progressView;
	private TextView durationView;
	private ImageButton playButton;
	private SeekBar seekbar;
	private String queueType = null;
	private boolean isDownloaded = false;
	//private boolean isDownloading = false;
	private String item_guid;
	private SeekBarListener seekBarListener = null;
	private PlayerService mPlayerService;
	private boolean isPlayerServiceBound = false;
    private ComponentName mRemoteControlResponder;
	private IntentFilter mIntentFilter;
	private final ServiceConnection mConnection = new ServiceConnection() {
	    @Override
		public void onServiceConnected(ComponentName className, IBinder service) {
	    	
	    	mPlayerService = ((PlayerService.LocalBinder)service).getService();
	    	
	    	if (PlayerService.PLAYING.equals(mPlayerService.state)
	    					&& item_guid.equals(mPlayerService.item_guid)) {
	    		
	    		playButton.setImageResource(android.R.drawable.ic_media_pause);	    		
	    		mUpdateHandler.post(mUpdateTimeTask);
	    	}
	    	else {
	    		playButton.setImageResource(android.R.drawable.ic_media_play);
	    		mPlayerService.item_guid = item_guid;
	    	}
	    }
	    @Override
		public void onServiceDisconnected(ComponentName className) {
	    	
	    	mPlayerService = null;
	    }
	};
	
	private final Handler mUpdateHandler = new Handler();
	private final Runnable mUpdateTimeTask = new Runnable() {
		@Override
		public void run() {

			if (PlayerService.PLAYING.equals(mPlayerService.state))
			{
				if (seekBarListener.tracking == false) {
				
					int progress = mPlayerService.mediaPlayer.getCurrentPosition();
					seekbar.setProgress(progress);
					progressView.setText(Util.timeIntToString(progress));
				}
				
				mUpdateHandler.postDelayed(this, 1000);
			}
			else {

				stop();
			}
		}
	};
    
	private final BroadcastReceiver mStatusListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        	
        	String action = intent.getAction();
        	
        	Log.d("PlayerActivity", "onReceive("+action+")");
        	
        	
        	/* If the event was not meant for us, return immediately */
        	if (!(PlayerService.SEEK.equals(action) || PlayerService.PLAYING.equals(action))
        			&& item_guid.equals(intent.getStringExtra("guid")) == false) {
        		return;
        	}
        	
        	
        	// Received a STOPPED event from the PlayerService
        	if (PlayerService.STOPPED.equals(action)) {
        		
        		stop();
        	}
        	/* Received DOWNLOADING event from the DownloadService
        	else if (DownloadService.DOWNLOADING.equals(action)) {
        		
        		if (item_guid.equals(intent.getStringExtra("guid")))
        		{
        			int progress = intent.getIntExtra("progress", 0);
	        		int percent = (int)(progress/100.0f*seekbar.getMax());
	        		seekbar.setSecondaryProgress(percent);
	        		
	        		if (progress < 100) {
	        			isDownloading = true;
	        		}
	        		else {
	        			isDownloading = false;
	        		}
        		}
        	}*/
        	else if (DownloadService.FINISHED_DOWNLOAD.equals(action)) {
        		
    			if (Util.isDownloaded(item_guid)) {
    				isDownloaded = true;
    				seekbar.setSecondaryProgress(seekbar.getMax());
    			}
    			//isDownloading = false;
        	}
        	// Received PLAYING event from the PlayerService.
        	// This happens *once* when the PlayerService begins playing
        	else if (PlayerService.PLAYING.equals(action))
        	{
        		String next_item_guid = intent.getStringExtra("next_item_guid");
        		
        		// The PlayerService has finished this Item and is starting the next.
        		// Update the Item and GUI
        		/*
        		if (item_guid.equals(prev_item_guid) && item_guid.equals(next_item_guid) == false)
        		{
        			// Update item
        			item.guid = next_item_guid;
        			item_guid = next_item_guid;
        			PodcastDB.getItem(getApplicationContext(), item);
        			item.position = mPlayerService.mediaPlayer.getCurrentPosition();
        			
        			// Update views
        			//updateGUI();
        		}
        		*/
        		
        		// At this point, this Item should match next_item_guid
        		if (item_guid.equals(next_item_guid))
        		{
        			playButton.setImageResource(android.R.drawable.ic_media_pause);
	        		mUpdateHandler.post(mUpdateTimeTask);
        		}
        	}
        	// Received SEEK event from the IntentHandler and we are not currently playing
        	// Update the progress because update handler is not running
        	else if (PlayerService.SEEK.equals(action) &&
        			(mPlayerService == null || mPlayerService.state != PlayerService.PLAYING))
        	{
        		int amount = fwd_seek_amount;
	        		
        		if (IntentHandler.PREVIOUS == intent.getIntExtra("direction", IntentHandler.PREVIOUS)) {
    				amount = rev_seek_amount;
    			}
        		
        		seek(seekbar.getProgress(), amount);
        	}
        }
	};

	
	
	
    @Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);
        setContentView(R.layout.player_layout);
        
        getActionBar().setDisplayHomeAsUpEnabled(true);
        
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        rev_seek_amount = -(Integer.parseInt(settings.getString(PodcastPreferenceActivity.REV_SEEK_PREF, "15")) * 1000);
        fwd_seek_amount = Integer.parseInt(settings.getString(PodcastPreferenceActivity.FWD_SEEK_PREF, "30")) * 1000;
        
        Intent intent = getIntent();
        
        queueType = intent.getStringExtra("queue_type");
        Log.d("PlayerActivity", "queueType: "+queueType);
        
        if (intent.hasExtra("guid")) {
        	
        	item_guid = intent.getStringExtra("guid");
        }
        else {
        	
        	item_guid = settings.getString("current_item_guid", null);
        }
        
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        
    	Log.d("PlayerActivity", "guid: "+item_guid);
    }
    
    
    
    
    @Override
	public void onResume()
    {
    	super.onResume();
    	
    	PodcastDB helper = new PodcastDB(getApplicationContext());
    	SQLiteDatabase db = helper.getReadableDatabase();
    	Cursor c = db.query(false, PodcastDB.ITEMS_TABLE, new String[] {"guid",
														                "channel_id",
														                "title",
														                "pubDate",
														                "position",
														                "size",
														                "duration",
														                "description"},
							"guid='"+item_guid+"'", null, null, null, null, null);
    	
    	if (c.moveToFirst()) {
    	
    		updateGUI(c.getString(0),
    				  c.getInt(1),
    				  c.getString(2),
    				  c.getString(3),
    				  c.getInt(4),
    				  c.getInt(5),
    				  c.getString(6),
    				  c.getString(7));
    	}
    	
    	c.close();
    	helper.close();
    	
    	
    	if (mIntentFilter == null) {

            mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(PlayerService.PLAYING);
            mIntentFilter.addAction(PlayerService.STOPPED);
            mIntentFilter.addAction(PlayerService.SEEK);
            mIntentFilter.addAction(DownloadService.FINISHED_DOWNLOAD);
        }
    	
    	registerReceiver(mStatusListener, mIntentFilter);
    	
    	
    	if (!isPlayerServiceBound) {
    		
    		bindService(new Intent(this,  PlayerService.class), mConnection, Context.BIND_AUTO_CREATE);
    		isPlayerServiceBound = true;
    	}
    	else if (item_guid.equals(mPlayerService.item_guid)) {
    		
    		// Already bound to the service.  Check the state
    		if (PlayerService.PLAYING.equals(mPlayerService.state)) {
    			
    			// Currently playing.  Update the button and re-start the timer
    			playButton.setImageResource(android.R.drawable.ic_media_pause);
    			mUpdateHandler.post(mUpdateTimeTask);
    		}
    		else {
    			
    			// Not playing.  Update the button
    			playButton.setImageResource(android.R.drawable.ic_media_play);
    		}
    	}
    	
    	
    	// Register media buttons
    	AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);    	
    	mRemoteControlResponder = new ComponentName(getPackageName(), IntentHandler.class.getName());
    	mAudioManager.registerMediaButtonEventReceiver(mRemoteControlResponder);
    }
    
    
    
    @Override
	public void onPause() {
    	
    	super.onPause();
    	
    	Log.d("PlayerActivity", "onPause()");
    	
    	mUpdateHandler.removeCallbacks(mUpdateTimeTask);
    	
    	unregisterReceiver(mStatusListener);
    }
    
    
    @Override
	public void onDestroy()
    {
    	super.onDestroy();
    	
    	Log.d("PlayerActivity", "onDestroy");
    	
    	if (isPlayerServiceBound) {
    		unbindService(mConnection);
    		isPlayerServiceBound = false;
    	}
    }
    
    
    
    
    public void buttonClicked(View view)
    {
    	switch(view.getId())
    	{
    	case R.id.play_button:
					if (mPlayerService != null
						&& item_guid.equals(mPlayerService.item_guid) 
						&& PlayerService.PLAYING.equals(mPlayerService.state)) {
						
						stop();
					}
					else {
						play();
					}
					break;
		
    	case R.id.seek_back_button:
					seek(seekbar.getProgress(), rev_seek_amount);
					break;
			
    	case R.id.seek_forward_button:
					seek(seekbar.getProgress(), fwd_seek_amount);
					break;
    	}
    }
    
    
    
    public void play()
    {
		final Intent intent = new Intent(getApplicationContext(), PlayerService.class);
		intent.setAction(PlayerService.PLAY);
		intent.putExtra("guid", item_guid);
		
		new Thread() {
			public void run() {
				startService(intent);
			}
		}.start();
    }
    
    
    
    public void stop()
    {
    	mUpdateHandler.removeCallbacks(mUpdateTimeTask);        
        playButton.setImageResource(android.R.drawable.ic_media_play);
        
        if (mPlayerService != null && PlayerService.PLAYING.equals(mPlayerService.state)) {
        	
        	new Thread() {
        		public void run() {
        			mPlayerService.stop();
        		}
        	}.start();
        }
    }
    
    
    public void seek(int progress, int delta) {
    	
    	Log.d("PlayerActivity", "seek - delta: "+delta);
    	
    	if (mPlayerService != null && PlayerService.PLAYING == mPlayerService.state) {
			
    		final Intent seekIntent = new Intent(this, PlayerService.class);
			seekIntent.setAction(PlayerService.SEEK);
			seekIntent.putExtra("guid", item_guid);
			seekIntent.putExtra("seek", delta);
			seekIntent.putExtra("beep", false);
			
			new Thread() {
				public void run() {
					startService(seekIntent);
				}
			}.start();
		}
		else {
			
			// Save position
			final int position = progress + delta;
			
			if (progress >= 0 && progress <= seekbar.getMax()) {
			
				progressView.setText(Util.timeIntToString(position));
		        if (seekBarListener.tracking == false) {
					seekbar.setProgress(position);
				}
		        
				new Thread() {
					public void run() {
						
						PodcastDB helper = new PodcastDB(getApplicationContext());
				    	SQLiteDatabase db = helper.getReadableDatabase();
				    	ContentValues values = new ContentValues();
				    	
				    	values.put("position", position);
						
				    	db.update(PodcastDB.ITEMS_TABLE, values, "guid='"+item_guid+"'", null);
				        
				        helper.close();
					}
				}.start();
			}
		}
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // app icon in action bar clicked; go home
                Intent intent = new Intent(this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    
    /*
    @Override
    public boolean onPrepareOptionsMenu(Menu menu)
    {
    	menu.clear();
    	
    	if (isDownloaded) {
    		
    		MenuItem removeDownloadMenuItem = menu.add(0, REMOVE_DOWNLOAD_MENU_ITEM, Menu.NONE, "Remove");
    		removeDownloadMenuItem.setIcon(R.drawable.ic_menu_delete);
    	}
    	else if (isDownloading) {
    		
    		MenuItem downloadMenuItem = menu.add(0, CANCEL_DOWNLOAD_MENU_ITEM, Menu.NONE, "Cancel Download");
    		downloadMenuItem.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
    	}
    	else {
    		
    		MenuItem downloadMenuItem = menu.add(0, DOWNLOAD_MENU_ITEM, Menu.NONE, "Download");
    		downloadMenuItem.setIcon(R.drawable.ic_menu_download);
    	}
    	
    	return true;
    }
    
    
    
    @Override
	public boolean onMenuItemSelected(int featureId, MenuItem menuItem)
    {   
    	switch(menuItem.getItemId())
    	{
    	case DOWNLOAD_MENU_ITEM:
    							isDownloading = true;
					    		Intent intent = new Intent(this, DownloadService.class);
					    		ArrayList<String> guids = new ArrayList<String>(1);
					    		guids.add(item_guid);
					    		intent.putStringArrayListExtra("guid", guids);
					    		intent.setAction(DownloadService.DOWNLOAD);
								startService(intent);
    							break;
    							
    	case REMOVE_DOWNLOAD_MENU_ITEM:
    							String filename = Util.getPodcastFilename(item_guid);
    							File file = new File(filename);
    							file.delete();
    							isDownloaded = false;
    							seekbar.setSecondaryProgress(0);
    							break;
    							
    	case CANCEL_DOWNLOAD_MENU_ITEM:
								Intent cancelIntent = new Intent(this, DownloadService.class);
								cancelIntent.setAction(DownloadService.CANCEL);
								cancelIntent.putExtra("guid", item_guid);
								startService(cancelIntent);
								isDownloading = false;
								break;
    	}
    	
    	return true;
    }
    */
    
    
    
    private void updateGUI(String guid,
    					   final int channel_id,
    					   String title,
    					   String pubDate,
    					   int position,
    					   int size,
    					   String duration,
    					   String description)
    {
    	final ImageView icon = (ImageView) findViewById(R.id.playing_layout_icon);
    	icon.setImageResource(R.drawable.default_thumbnail);
    	
    	ViewTreeObserver vto = icon.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
            	new PlayingActivityDownloadIconTask(channel_id, icon).execute();
            	icon.getViewTreeObserver().removeOnPreDrawListener(this);
                return true;
            }
        });
    	
    	
    	TextView age = (TextView) findViewById(R.id.playing_layout_age);
    	age.setText(Util.getItemAge(pubDate));
    	
    	TextView itemTitle = (TextView) findViewById(R.id.playing_layout_item_title);
    	itemTitle.setText(title);
    	
    	TextView itemDescription = (TextView) findViewById(R.id.playing_layout_item_description);
    	itemDescription.setText(description);
    		
    	if (playButton == null) {
    		playButton = (ImageButton) findViewById(R.id.play_button);
    	}
    	
    	if (progressView == null) {
    		progressView = (TextView) findViewById(R.id.position);
    	}
    	progressView.setText(Util.timeIntToString(position));
    	
    	
    	int durationInt = 0;
    	if (duration == null) {
    		MediaPlayer player = new MediaPlayer();
    		try {
    			player.setDataSource(Util.getPodcastFilename(guid));
    			player.prepare();
    			durationInt = player.getDuration();
    			duration = Util.timeIntToString(durationInt);
    		}
    		catch (IOException e) {
    			e.printStackTrace();
    		}
    		finally {
    			player.release();
    		}
    	}
    	else {
    		durationInt = PlayerActivity.timeStringToInt(duration);
    	}
    	
    	
    	if (durationView == null) {
    		durationView = (TextView) findViewById(R.id.duration);
    		durationView.setText(duration);
    	}
    	
    	if (seekBarListener == null) {
    		seekBarListener = new SeekBarListener();
    	}
    	
    	isDownloaded = Util.isDownloaded(guid);
    	
    	if (seekbar == null) {
    		seekbar = (SeekBar) findViewById(R.id.progress_bar);
    		seekbar.setOnSeekBarChangeListener(seekBarListener);
    	}
    	
    	seekbar.setMax(durationInt);
    	seekbar.setProgress(position);
    	
    	if (isDownloaded) {
    		seekbar.setSecondaryProgress(seekbar.getMax());
    	}
    	else {
    		
    		File tmpFile = new File(Util.getPodcastFilename(guid)+".tmp");
    		if (size > 0 && tmpFile.exists()) {
    			
    			seekbar.setSecondaryProgress((int)(tmpFile.length()/(float)size*seekbar.getMax()));
    		}
    		else {
    			
    			seekbar.setSecondaryProgress(0);
    		}
    	}
    	
    	
    	TextView channelTitle = (TextView) findViewById(R.id.playing_layout_channel_title);
    	TextView authors = (TextView) findViewById(R.id.playing_layout_authors);
    	
    	// Get the channel from the db
    	PodcastDB helper = new PodcastDB(this);
    	SQLiteDatabase db = helper.getReadableDatabase();
        Cursor c = db.query(true, PodcastDB.CHANNELS_TABLE, new String[] {"title", "author"},
                            "_id="+channel_id, null, null, null, null, null);
        
        if (c.moveToFirst())
        {
           channelTitle.setText(c.getString(0));
           authors.setText(c.getString(1));
        }

        c.close();
        helper.close();
    }
    
    
    
    public class PlayingActivityDownloadIconTask extends DownloadIconTask
    {
    	public PlayingActivityDownloadIconTask(int channel_id, ImageView view) {
    		
    		super(PodcastDB.getImageURL(getApplicationContext(), channel_id), view);
    	}
    	
    	@Override
    	public void onPreExecute() {
    		
    		networkAvailable = Util.isNetworkAvailable(PlayerActivity.this);
    	}
    	
    	@Override
    	protected void onPostExecute(Bitmap bitmap)
    	{    		
    		if (bitmap != null)
    		{
    			ImageView view = imageViewReference.get();
				
    			if (view != null)
    			{
					TransitionDrawable drawable = new TransitionDrawable(
							new Drawable[] {view.getDrawable(), new BitmapDrawable(bitmap)});
					
					view.setImageDrawable(drawable);
					drawable.setCrossFadeEnabled(true);
					drawable.startTransition(500);
    			}
    		}
    	}
    }
    
    
    
    private class SeekBarListener implements SeekBar.OnSeekBarChangeListener
    {
    	private boolean tracking = false;
    	private int startProgress;
    	
    	@Override
		public void onStopTrackingTouch(SeekBar seekBar) {
    		seek(startProgress, seekBar.getProgress()-startProgress);
			tracking = false;
		}
		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {
			startProgress = seekBar.getProgress();
			tracking = true;
		}
		@Override
		public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
		}
    }
    
    
    
    private static int timeStringToInt(String time)
    {
    	if (time == null) {
    		return 0;
    	}
    	
    	int seconds = 0;
    	String[] tArr = time.split(":");
    	
    	for (int i=tArr.length-1; i >= 0; i--) {
    		seconds += Integer.parseInt(tArr[i]) * Math.pow(60, tArr.length-1-i);
    	}
    	
    	return seconds*1000;
    }

    
}
